import { inject, computed, type Slots, provide, h } from 'vue'
import type { RouteLocationNormalizedLoaded } from 'vue-router'

export const RouterView = {
  name: 'RouterView',
  setup(_: unknown, { slots }: { slots: Slots }) {
    // 当我们进行组件渲染的时候，这里会存在一个层级的关系
    // 因为 matched 是一个有层次关系（父子关系）的组件数组，意味着 router-view 可能存在好几个
    // 所以这里存在一个“深度”的问题

    // 这里可以通过 inject 的方法，从父组件那里去获取 depth
    // 根据 depth 来得知当前的 router-view 是第几层
    // 如果父组件没有提供 depth，说明这是最顶层的 router-view，我们给一个默认值 0
    const depth: number = inject('depth', 0)
    const injectRoute: RouteLocationNormalizedLoaded = inject('route location')!

    // 获取对应层数的匹配上的路由记录
    const matchedRouteRef = computed(() => injectRoute.matched[depth])

    // 第一次执行完成后，我们要使其 +1
    // 把这些信息提供给下一层
    provide('depth', depth + 1)
    provide('router view location matched', matchedRouteRef)

    // 返回一个渲染函数，这个函数在每次重新渲染的时候会被调用
    return () => {
      // 获取对应的路由记录
      const matchRoute = matchedRouteRef.value
      // 从路由记录上面获取到组件
      const viewComponent = matchRoute && matchRoute?.components?.default

      // 查看组件是否存在
      if (!viewComponent) {
        // 进入到此 if，说明没有找到对应的组件
        // 那么就渲染默认的插槽（如果有的话）
        return slots.default && slots.default()
      }

      // 找到了对应的组件
      // 渲染该组件
      return h(viewComponent)
    }
  }
}

